package com.flying.admin.service;

import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSONObject;
import com.flying.common.annotation.DaoCreate;
import com.flying.common.annotation.DaoQuery;
import com.flying.common.annotation.DaoRemove;
import com.flying.common.annotation.DaoUpdate;
import com.flying.common.http.JsonHttpUtils;
import com.flying.common.util.Codes;
import com.flying.common.util.JSONUtils;
import com.flying.common.util.Pair;
import com.flying.common.util.Utils;
import com.flying.framework.annotation.MethodInfo;
import com.flying.framework.annotation.Param;
import com.flying.framework.annotation.Service;
import com.flying.framework.annotation.event.Event;
import com.flying.framework.annotation.event.Handler;
import com.flying.framework.data.Data;
import com.flying.framework.service.AbstractService;

@Service(value="ModuleDeploy", desc="模块部署", events={
		@Event(trigger="deploy",		handlers={@Handler(serviceId="ModuleDeployLog:create")})
})
public class ModuleDeploy extends AbstractService{
	public final static String TABLE_NAME = "sys_module_deploy";
	
	private App app;
	private Module module;
	
	public void setAppService(App app) {
		this.app = app;
	}
	
	public void setModuleService(Module m) {
		this.module = m;
	}
	
	public enum Field {
		
		app_id         ("app_id",            "String",	"应用ID"),
		module_id      ("module_id",         "String",	"模块ID"),
		version        ("version",           "String",	"模块版本"),
		deploy_date    ("deploy_date",       "Date",	"部署时间"),
		status         ("status",            "int",	"状态(1:正常;0:异常)"),
		tag            ("tag",               "String",	"用途标签");
		
		public final String fieldName;
		public final String fieldType;
		public final String fieldComment;
	
		Field(String name, String dataType, String comment) {
			this.fieldName 		= name;
			this.fieldType		= dataType;
			this.fieldComment	= comment;
		}
	}
	
	@MethodInfo("在应用上安装模块")
	public Data install(
			@Param(value="appId",             required=true,	desc="应用ID") String appId,
			@Param(value="moduleId",          required=true,	desc="模块ID") String moduleId,
			@Param(value="path",              required=true,	desc="模块安装本地目录或下载文件URL") String path) throws Exception {

		Data app = this.app.findById(appId);
		final String host_address = app.getString(App.Field.host_address.fieldName);
		final int port = app.getInteger(App.Field.port.fieldName, 8080);
		//
		List<Pair<String, String>> params = Utils.newArrayList();
		params.add(new Pair<String, String>("action", 	"install"));
		params.add(new Pair<String, String>("moduleId", moduleId));
		params.add(new Pair<String, String>("locate", 	"local"));
		params.add(new Pair<String, String>("path", 	path));
		JSONObject jo = JsonHttpUtils.post("http://"+host_address+":"+port+"/manage", params);
		return new Data(JSONUtils.toMap(jo));
	}
	
	@MethodInfo("在应用上卸载模块")
	public Data uninstall(
			@Param(value="appId",             required=true,	desc="应用ID") String appId,
			@Param(value="moduleId",          required=true,	desc="模块ID") String moduleId) throws Exception {

		Data app = this.app.findById(appId);
		final String host_address = app.getString(App.Field.host_address.fieldName);
		final int port = app.getInteger(App.Field.port.fieldName, 8080);
		//
		List<Pair<String, String>> params = Utils.newArrayList();
		params.add(new Pair<String, String>("action", 	"uninstall"));
		params.add(new Pair<String, String>("moduleId", moduleId));
		JSONObject jo = JsonHttpUtils.post("http://"+host_address+":"+port+"/manage", params);
		return new Data(JSONUtils.toMap(jo));
	}

	@MethodInfo("登记发布在应用中的模块")
	public Data deploy(
			@Param(value="appId",             required=true,	desc="应用ID") String appId,
			@Param(value="moduleId",          required=true,	desc="模块ID") String moduleId,
			@Param(value="version",           required=true,	desc="版本号") String version,
			@Param(value="hostName",          required=true,	desc="所属主机名称") String hostName,
			@Param(value="hostAddress",       required=true,	desc="所属主机IP") String hostAddress,
			@Param(value="path",              required=true,	desc="模块安装目录") String path) throws Exception {
		
		Data app = this.app.findById(appId);
		if(app.getInteger(Codes.CODE, -1) != Codes.SUCCESS) {
			app = this.app.create(appId, appId, hostName, hostAddress, 8080, null, null);
		}
		
		Data module = this.module.findById(moduleId);
		if(module.getInteger(Codes.CODE, -1) != Codes.SUCCESS) {
			this.module.create(moduleId, version, moduleId, null);
		}
		
		Data result = this.update(appId, moduleId, version, path, new Date(), 1, null, null);
		if(result.getInteger(Codes.EFFECT_ROWS, 0) == 0)
			return this.create(appId, moduleId, version, path, new Date(), 1, null);
		else
			return result;
	}
	
	@MethodInfo("创建模块部署")
	@DaoCreate(entity="sys_module_deploy")
	public Data create(
		
			@Param(value="app_id",            required=true,	desc="应用ID") String app_id,
			@Param(value="module_id",         required=true,	desc="模块ID") String module_id,
			@Param(value="version",           required=true,	desc="模块版本") String version,
			@Param(value="path",              required=true,	desc="模块安装目录") String path,
			@Param(value="deploy_date",       required=false,	desc="部署时间") Date deploy_date,
			@Param(value="status",            required=false,	desc="状态(1:正常;0:异常)") int status,
			@Param(value="tag",               required=false,	desc="用途标签") String tag
		
		) throws Exception {
		
		return null;
	}

	@MethodInfo("修改模块部署")
	@DaoUpdate(entity="sys_module_deploy")
	public Data update(
		
			@Param(value="app_id",            required=false,	desc="应用ID",	tag="where") String app_id,
			@Param(value="module_id",         required=false,	desc="模块ID",	tag="where") String module_id,
			@Param(value="version",           required=false,	desc="模块版本") String version,
			@Param(value="path",              required=true,	desc="模块安装目录") String path,
			@Param(value="deploy_date",       required=false,	desc="部署时间") Date deploy_date,
			@Param(value="status",            required=false,	desc="状态(1:正常;0:异常)") int status,
			@Param(value="tag",               required=false,	desc="用途标签") String tag,
			@Param(value="fields", required=false, desc="更新字段", tag="fields") String[] fields
			
		) throws Exception {
		
		return null;
	}

	@MethodInfo("修改标签")
	@DaoUpdate(entity="sys_module_deploy")
	public Data updateTag(
		
			@Param(value="app_id",            required=false,	desc="应用ID",	tag="where") String app_id,
			@Param(value="module_id",         required=false,	desc="模块ID",	tag="where") String module_id,
			@Param(value="tag",               required=false,	desc="用途标签") String tag
			
		) throws Exception {
		
		return null;
	}

	@MethodInfo("删除模块部署")
	@DaoRemove(entity="sys_module_deploy")
	public Data remove(
		
			@Param(value="app_id",            required=true,	desc="应用ID") String app_id,
			@Param(value="module_id",         required=true,	desc="模块ID") String module_id
		
		) throws Exception {
		
		return null;
	}

	@MethodInfo("查询所有模块部署")
	@DaoQuery(entity="sys_module_deploy")
	public Data findAll() throws Exception {
		return null;
	}

	@MethodInfo("查询模块部署的网点")
	@DaoQuery(entity="sys_module_deploy")
	public Data findByModuleId(
			@Param(value="module_id",         required=true,	desc="模块ID") String module_id) throws Exception {
		return null;
	}

	@MethodInfo("根据主键查询模块部署")
	@DaoQuery(entity="sys_module_deploy", single=true)
	public Data findById(
		
			@Param(value="app_id",            required=true,	desc="应用ID") String app_id,
			@Param(value="module_id",         required=true,	desc="模块ID") String module_id
		
		) throws Exception {
		return null;
	}

}